/**
 * 全局异常控制器 另外的写法
 */
@Slf4j
@RestControllerAdvice
@Order(260)
@ResponseBody
public class GlobalExceptionHandler {
    /**
     * controller层验证未通过
     *
     * @param e 未通过的异常
     * @return 错误消息
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result<Object> methodArgumentNotValidException(MethodArgumentNotValidException e) {
        log.info("MethodArgumentNotValidException Validation Failed", e);
        BindingResult bindingResult = e.getBindingResult();
        return buildResult(bindingResult);
    }

    private static Result<Object> buildResult(BindingResult bindingResult) {
        List<FieldError> fieldErrors = bindingResult.getFieldErrors();
        Result<Object> failure = Results.failure(FailureCode.PARAMETER_ERROR);
        if (!CollectionUtils.isEmpty(fieldErrors)) {
            failure.setViolationItems(fieldErrors.stream()
                    .map(item -> new Result.ViolationItem(item.getField(), item.getDefaultMessage()))
                    .collect(Collectors.toList()));
        }
        failure.setTraceId(TraceContext.traceId());
        return failure;
    }

    /**
     * BindException
     *
     * @param e 未通过的异常
     * @return 错误消息
     */
    @ExceptionHandler(BindException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result<Object> methodBindException(BindException e) {
        log.info("BindException Validation Failed", e);
        BindingResult bindingResult = e.getBindingResult();
        return buildResult(bindingResult);
    }

    /**
     * 拦截 业务异常
     */
    @ExceptionHandler(ServiceErrorException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result<?> businessException(ServiceErrorException e) {
        log.info("业务异常 - 异常编号：{} - 异常信息：{}", e.getCode(), e.getMessage(), e);
        Result<Object> error = Result.error(Integer.parseInt(e.getCode()), e.getMessage());
        error.setTraceId(TraceContext.traceId());
        return error;
    }

    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(value = BizException.class)
    public Result<Void> bizException(BizException exception) {
        log.info("BizException exception", exception);
        Result<Void> failure = Results.failure(exception);
        failure.setTraceId(TraceContext.traceId());
        return failure;
    }

    @ExceptionHandler(InvalidFormatException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result<Void> argFormatException(InvalidFormatException exception) {
        log.info("InvalidFormatException Validation Failed", exception);
        Result<Void> error = Results.err(ErrorCode.FORMAT_ERROR, exception.getMessage());
        error.setTraceId(TraceContext.traceId());
        return error;
    }

    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(value = Exception.class)
    public Result<Void> serviceErrorException(Exception exception) {
        log.info("unKnown exception", exception);
        Result<Void> err = Results.err(ErrorCode.UNKNOWN_ERROR, exception.getMessage());
        err.setTraceId(TraceContext.traceId());
//        err.setMessage(ErrorCode.UNKNOWN_ERROR.message());
        return err;
    }

}